<?php

//导入系统环境
require_once("../control/interface.php");

/*
系统公共数据处理类
*/

class libDataClass
{
    use control\interfaces;

    /**
     * 管理员登录
     *
     * @param array $data
     * @return array
     * @throws Exception
     */
    public function adLogin(array $data): array
    {
        if (empty($data['post']['userName'])) {
            $json['warn'] = "请输入用户名";
        } elseif (preg_match(checkString, $data['post']['userName']) == 0) {
            $json['warn'] = "用户名格式有误";
        } elseif (empty($data['post']['password'])) {
            $json['warn'] = "请输入登录密码";
        } elseif (strlen($data['post']['password']) < 6 || strlen($data['post']['password']) > 20) {
            $json['warn'] = "登录密码不得低于六位或大于20位";
        } elseif (empty($data['post']['prove'])) {
            $json['warn'] = "请输入验证码";
        } elseif ($data['post']['prove'] != $_SESSION["yan"]) {
            $json['warn'] = "验证码输入错误";
        } elseif (empty($data['post']['did'])) {
            $json['warn'] = "登录设备异常";
        } else {
            $password = $data['post']['password'];

            $user       = query("user", " userName = '" . $data['post']['userName'] . "' ");
            $adLoginNum = para("adLoginNum");//每日登录密码最大的错误次数
            /*if (empty($user['userName'])) {
                $json['warn'] = "用户名【" . $data['post']['userName'] . "】不存在";
            } else*/
            if ($user['loginError'] >= $adLoginNum and $user['loginErrorDay'] == date("Y-m-d")) {
                $json['warn'] = "您今天登录密码输入错误次数已经超过" . $adLoginNum . "次，不能再登录了";
            } elseif ($user['state'] == "停用") {
                $json['warn'] = "您的账号处于停用状态，请联系行政人员！";
            } //登录密码输入错误
            elseif (verifyPwd($password, $user['password']) !== true) {
                if (isset($_SESSION['forgetPas']) && $data['post']['userName'] == $_SESSION['forgetPas']['name'] and verifyPwd($password, $_SESSION['forgetPas']['prove'])) {
                    //如果是点击忘记密码时发送到手机上的短信验证码
                    update([
                        "table" => "user",
                        "field" => [
                            "password"   => md5s($data['post']['password']),
                            "updateTime" => date("Y-m-d H:i:s"),
                        ],
                        "where" => " userName = '" . $data['post']['userName'] . "' ",
                    ]);
                    unset($_SESSION['forgetPas']['prove']);
                    $json['warn'] = 2;
                } else {
                    if($user['uid']) {
                        if ($user['loginError'] >= $adLoginNum) {
                            $user['loginError'] = 0;
                        }
                        $num    = (int)$user['loginError'] + 1;
                        $remain = $adLoginNum - $num;//今天还能登录的次数
                        update([
                            "table" => "user",
                            "field" => [
                                "loginError"    => $num,
                                "loginErrorDay" => date("Y-m-d"),
                                "updateTime"    => date("Y-m-d H:i:s"),
                            ],
                            "where" => " userName = '" . $data['post']['userName'] . "' ",
                        ]);
                        $json['warn'] = "账号或密码错误，您今天还可以登录" . $remain . "次";
                    }else{
                        $json['warn'] = "账号或密码错误";
                    }
                }
            } else {
                $json['warn'] = 2;
            }
            if ($json['warn'] == 2) {
                $this->rSet($user['uid'] . 'loginPage', 1);
                //登录密码错误次数清零
                update([
                    "table" => "user",
                    "field" => [
                        'deviceId'   => $data['post']['did'],
                        'loginError' => 0,
                    ],
                    "where" => " userName = '" . $data['post']['userName'] . "' ",
                ]);
                $record = query('user_setting', "stid = '" . $user['stid'] . "' and type = '当前使用账套'");
                //添加登录记录
                insert([
                    "table" => "log",
                    "field" => [
                        "type" => "user",
                        "coid" => $record['value'],
                        "stid" => $user['stid'],
                        "text" => $user['name'] . "登录了管理员后台，ip地址：" . getIp(),
                        "time" => date("Y-m-d H:i:s"),
                    ],
                ]);
                //创建登录session，返回跳转地址
                $_SESSION['stid']     = $user['stid'];
                $_SESSION['deviceId'] = $data['post']['did'];
                $json['href']         = root . "control/adIndex.html";
            }
        }
        return $json;
    }

    /**
     * 获取企业微信扫码登录参数
     */
    public function getPara($data): array
    {
        return [
            'appid'   => para('qyWeChatCorpid'),
            'agentid' => para('qyWeChatQrAppId'),
            'url'     => urlencode(root . 'control/qyLoginClass.html?did=' . $data['post']['did']),
            'nonstr'  => self::getId(),
        ];
    }

    /**N
     * 短信验证码
     *
     * @param array $data
     * @return array
     */
    public function newProve(array $data): array
    {
        //赋值
        $tel     = $data['post']['tel']; //需要发送短信的手机号码
        $session = $_SESSION['prove'];   //保存到session中的验证信息
        $oldTime = $session['time'] + 60;//最后一次发送验证码的时间不得晚于此时间
        //判断并执行
        if (empty($tel)) {
            $json['warn'] = "请输入注册手机号码";
        } elseif (preg_match(checkTel, $tel) == 0) {
            $json['warn'] = "手机号码输入错误";
        } elseif ($oldTime > time() and $session['tel'] == $tel) {
            $json['warn'] = "发送验证码间隔不能超过一分钟";
        } else {
            $rand = rand(10000, 99999);
            //发送短信
            sms(array(
                "tel"           => $tel,
                "TemplateCode"  => "para('aliyunTemplateCode')",
                "TemplateParam" => array("code" => $rand),
            ));
            //返回
            $_SESSION['prove'] = array("rand" => $rand, "time" => time(), "tel" => $tel);
            $json['warn']      = "发送成功";
        }
        return $json;
    }

    /**
     * 重置密码
     *
     * @param array $data
     * @return array
     */
    public function adForgetPassword(array $data): array
    {
        //赋值
        $session = getVal($_SESSION, 'forgetPas');                       //防止重复发送短信的session
        $oldTime = ($session['time'] ?? 0) + 60;//最后一次发送验证码的时间不得晚于此时间
        //判断
        if (empty($data['post']['name'])) {
            $json['warn'] = "用户名不能为空";
        } elseif (preg_match(checkString, $data['post']['name']) == 0) {
            $json['warn'] = "用户名格式有误";
        } elseif ($oldTime > time() and $session['name'] == $data['post']['name']) {
            $json['warn'] = "发送验证码间隔不能低于一分钟";
        } else {
            $user = query("user", " userName = '" . $data['post']['name'] . "' ");
            if (empty($user['userName'])) {
                $json['warn'] = "用户名不存在";
            } elseif (empty($user['tel'])) {
                $json['warn'] = "此用户没有登记手机号码";
            } elseif (preg_match(checkTel, $user['tel']) == 0) {
                $json['warn'] = "此用户手机号码格式有误";
            } else {
                //生成随机六位短信验证码
                $prove = rand(100000, 999999);
                //发送短信
                sms([
                    "tel"           => $user['tel'],
                    "TemplateCode"  => para('aliyunTemplateCodeReset'),
                    "TemplateParam" => ["code" => $prove],
                ]);
                //返回
                $_SESSION['forgetPas'] = ["time" => time(), "name" => $data['post']['name'], "prove" => md5s($prove)];
                $json['warn']          = "发送成功";
            }
        }
        return $json;
    }

    /*根据省份获取下属城市下拉菜单内容值*/
    public function getCity($data)
    {
        $json['city'] = repeatSelect(array(
            "type"     => "option",
            "sqlForm"  => " region where province = '" . $data['post']['province'] . "' ",
            "sqlField" => "city",
            "name"     => "city",
            "title"    => "城市",
        ));
        return $json;
    }

    /*根据省份和城市获取下属区域下拉菜单*/
    public function getArea($data)
    {
        $json['area'] = idSelect(array(
            "type"     => "option",
            "sqlForm"  => " region where province = '" . $data['post']['province'] . "' and city = '" . $data['post']['city'] . "' ",
            "sqlId"    => "id",
            "sqlField" => "area",
            "name"     => "area",
            "title"    => "区域",
        ));
        return $json;
    }

    /*异步加载通用文章某段内容*/
    public function getArticleText($data)
    {
        $article      = query("article", " id = '" . $data['post']['articleId'] . "' ");
        $json['word'] = html_entity_decode($article['word'], ENT_QUOTES);
        return $json;
    }

    /*通用文章管理-新增或更新文字段落*/
    public function articleWordEdit($data)
    {
        //赋值
        $field = array(
            "type"       => $data['post']['type'],//文章分类
            "typeId"     => $data['post']['typeId'],//分类id
            "word"       => $data['post']['word'],//段落内容
            "updateTime" => date("Y-m-d H:i:s"),//更新时间
        );
        $id    = $data['post']['articleId'];//段落ID号
        //判断
        if (empty($field['type'])) {
            $json['warn'] = "文章分类为空";
        } elseif (empty($field['word'])) {
            $json['warn'] = "您还没有填写文字呢";
        } elseif (empty($id)) {
            $articleLast  = query("article", " typeId = '$field[typeId]' order by list desc ");
            $list         = $articleLast['list'] + 1;
            $id           = suiji();
            $field        = array_merge($field, array("id" => $id, "list" => $list, "time" => date("Y-m-d H:i:s")));
            $json['warn'] = insert(array("table" => "article", "field" => $field));
        } else {
            $json['warn'] = update(array("table" => "article", "field" => array("word" => $field['word'], "updateTime" => date("Y-m-d H:i:s")), "where" => " id = '$id' "));
        }
        //提示
        if (in_array($json['warn'], array("新增成功", "更新成功"))) {
            $_SESSION['warn'] = $json['warn'];
            $json['warn']     = 2;
        }
        //返回
        return $json;
    }

    /*通用文章管理-更新序列号*/
    public function articleListEdit($data)
    {
        //赋值
        $field   = array(
            "list"       => $data['post']['articleListText'],//排序号
            "updateTime" => date("Y-m-d H:i:s"),//更新时间
        );
        $article = query("article", " id = '" . $data['post']['artcleListId'] . "' ");//段落ID号
        if (empty($field['list'])) {
            $json['warn'] = "排序号不能为空";
        } elseif (preg_match(checkInteger, $field['list']) == 0) {
            $json['warn'] = "排序号必须为正整数";
        } elseif (empty($article['id'])) {
            $json['warn'] = "未找到此段落";
        } else {
            $json['warn'] = update(array("table" => "article", "field" => $field, "where" => " id = '$article[id]' "));
            //提示
            if ($json['warn'] == "更新成功") {
                $_SESSION['warn'] = $json['warn'];
                $json['warn']     = 2;
            }
        }
        //返回
        return $json;
    }

    /*通用文章管理-新增或更新图片*/
    public function articleImgEdit($data)
    {
        //判断
        if (empty($data['post']['type'])) {
            $warn = "文章分类为空";
        } elseif (empty($data['post']['typeId'])) {
            $warn = "未找到此记录";
        } elseif (empty($data['post']['folder'])) {
            $warn = "图片文件夹名称为空";
        } elseif (empty($data['post']['maxWidth'])) {
            $warn = "图片最大宽度为空";
        } else {
            $para = array(
                "fileName"  => "imgFile",//上传图片的表单文件域名称
                "make"      => "缩放图像",//处理方式：裁剪图像、缩放图像、空
                "field"     => "img",//存放图片根目录的数据库字段名
                "maxNum"    => 100,//新增图像时限定的图像总数
                "newWidth"  => $data['post']['maxWidth'],//新图像的宽度
                "newHeight" => "",//新图像的高度，图像裁剪时必须
                "maxHeight" => 5000,//缩放后图片的最大高度
            );
            //拼接新图片保存的网站根目录位置
            $para['url'] = "img/articleImg/" . $data['post']['folder'];
            if (!file_exists(serverRoot . $para['url'])) {
                mkdir(serverRoot . $para['url']);
            }
            $para['url'] .= "/" . suiji() . ".jpg";
            //判断是新增图像还是更新图像
            if (empty($data['post']['id'])) {
                $para['type']      = "新增图像";                                                                                 //插入类型：更新图像、新增图像
                $para['sqlSearch'] = "select * from article where typeId = '" . $data['post']['typeId'] . "' and word = '' ";    //查询图片的数据库代码
                $lastArticle       = query("article", " typeId = '" . $data['post']['typeId'] . "' order by list desc");
                $newList           = $lastArticle['list'] + 1;
                $articleId         = suiji();
                $anchor            = "#" . $articleId;
                //数据库图片处理代码
                $field         = array(
                    "id"           => $articleId,
                    "type"         => $data['post']['type'],
                    "typeId"       => $data['post']['typeId'],
                    $para['field'] => $para['url'],
                    "list"         => $newList,
                    "updateTime"   => date("Y-m-d H:i:s"),
                    "time"         => date("Y-m-d H:i:s"),
                );
                $para['sqlIn'] = array("table" => "article", "field" => $field);
            } else {
                $para['type']      = "更新图像";
                $para['sqlSearch'] = " select * from article where id = '" . $data['post']['id'] . "' ";
                $para['sqlIn']     = array("table" => "article", "field" => array($para['field'] => $para['url'], "updateTime" => date("Y-m-d H:i:s")), "where" => " id = '" . $data['post']['id'] . "' ");
                $anchor            = "#" . $data['post']['id'];
            }
            $warn             = imgUpdate($para);
            $_SESSION['warn'] = $warn;
            header("location:" . getenv("HTTP_REFERER") . $anchor);
            exit(0);
        }
    }

    /*通用文章管理-删除段落*/
    public function articleDelete($data)
    {
        //赋值
        $article = query("article", " id = '" . $data['get']['id'] . "' ");
        //判断
        if (empty($data['get']['id'])) {
            $_SESSION['warn'] = "段落ID号为空";
        } elseif (empty($article['id'])) {
            $_SESSION['warn'] = "未找到此段落";
        } else {
            //删除图片
            fileDelete($article['img']);
            //删除数据库记录
            delete(array("table" => "article", "where" => " id = '$article[id]' "));
            //返回信息
            $_SESSION['warn'] = "本段内容删除成功";
            //跳转
            $articleList = $article['list'] - 1;
            $lastArticle = query("article", " typeId = '$article[typeId]' and list = '$articleList' ");
            $anchor      = "#" . $lastArticle['id'];
            header("location:" . getenv("HTTP_REFERER") . $anchor);
            exit(0);
        }
    }

    /*图形验证码*/
    public function proveImg()
    {
        header("content-type:image/png");
        $image_width  = 100;
        $image_height = 37;
        $new_number   = "1234567890";
        $num_image    = imagecreate($image_width, $image_height);
        imagecolorallocate($num_image, 255, 255, 255);
        $str = "";
        for ($i = 0; $i < 4; $i++) {
            //随机字体
            $font   = mt_rand(3, 5);
            $x      = mt_rand(1, 8) + $image_width * $i / 4;
            $y      = mt_rand(1, $image_height / 4);
            $color  = imagecolorallocate($num_image, mt_rand(0, 200), mt_rand(0, 150), mt_rand(0, 200));
            $number = $new_number[rand(0, 9)];
            $str    .= $number;
            $x1     = mt_rand(1, 32);
            $y1     = mt_rand(1, 32);
            imagestring($num_image, $font, $x, $y, $number, $color);
            imageline($num_image, $x1, $y1, $x, $y, $color);//画干扰线
        }
        $_SESSION["yan"] = $str;
        imagepng($num_image);
        imagedestroy($num_image);
        exit();
    }

    /*返回*/
    public function html($data)
    {
        //判断主体
        $type = $data['get']['type'];
        if (!method_exists(__CLASS__, $type)) {
            $json['warn'] = "未知执行指令";
        } else {
            $json = $this->$type($data);
        }
        //返回
        return json_encode($json, 320);
    }

    /**
     * 备份函数
     *
     * @return void
     */
    public function automatic()
    {
        if (para("automatic") !== date("Ymd")) {
            //更新处理日期
            paraEdit("automatic", date("Ymd"));
            // 备份数据库
            $this->backUp();
            //还原数据库
            //$this->mySqlRestore($data);
        }
    }

    private static function addFileToZip($path, $zip)
    {
        $handler = opendir($path);
        while (($filename = readdir($handler)) !== false) {
            //文件夹文件名字为'.'和‘..'，不要对他们进行操作
            if ($filename != "." && $filename != "..") {
                // 如果读取的某个对象是文件夹，则递归
                if (is_dir($path . "/" . $filename)) {
                    self::addFileToZip($path . "/" . $filename, $zip);
                } else {
                    $zip->addFile($path . "/" . $filename, basename($filename));
                }
            }
        }
        @closedir($handler);
    }

    private function backUp()
    {
        $newUrl = "backups/" . date('Ymd');
        if (file_exists($newUrl) === false) {
            //如果根目录不存在存放数据库文件的文件夹，则创建
            if (!file_exists($newUrl)) {
                self::_mkdir($newUrl);
            }
            //将最新的数据库保存到新建的文件夹中
            $this->dataBackup($newUrl);
            // 打包
            $zip     = new ZipArchive();
            $dirPath = '../' . $newUrl;
            $zipPath = serverRoot . $newUrl . '_' . uniqid() . '.zip';
            if ($zip->open($zipPath, ZipArchive::CREATE) === true) {
                self::addFileToZip($dirPath, $zip);
                $zip->close();
                // 删除文件
                self::deleteFile($dirPath);
            }
            //删除超过30天的文件夹
            $fileArray = glob(serverRoot . "backups/*");
            $starTime  = strtotime(date("Ymd")) - 3600 * 24 * 30;
            foreach ($fileArray as $filePath) {
                $fileMtime = filemtime($filePath);
                if ($fileMtime < $starTime) {
                    unlink($filePath);
                }
            }
        }
    }

    /**
     * 备份主函数
     *
     * @param string $path 要备份的路径
     */
    private static function dataBackup($path)
    {
        global $con;
        $res = mysqli_query($con, "SHOW TABLES");
        while ($row = mysqli_fetch_array($res)) {
            self::backupTable($row[0], $path);
        }
        mysqli_free_result($res);
        mysqli_close($con);
    }

    /**
     * 备份表
     *
     * @param string $table 数据表名
     * @param string $path 要备份的路径
     */
    private static function backupTable($table, $path)
    {
        global $con;
        $data = '';
        $file = serverRoot . $path . '/' . $table . ".sql"; //存放路径
        //构造表结构语句
        $res  = mysqli_query($con, "SHOW CREATE TABLE `$table` ");
        $row  = mysqli_fetch_array($res);
        $data .= $row['Create Table'] . ";\r\n";
        //构造插入数据语句
        $res2 = mysqli_query($con, "SELECT * FROM `$table` ");
        while ($arr = mysqli_fetch_assoc($res2)) {
            $keys = array_keys($arr);
            $keys = array_map('addslashes', $keys);
            $keys = join('`,`', $keys);
            $keys = "`" . $keys . "`";
            $val  = array_values($arr);
            $val  = array_map('addslashes', $val);
            $val  = join("','", $val);
            $val  = "'" . $val . "'";
            $data .= "INSERT IGNORE INTO `$table`($keys) VALUES ($val);\r\n";
        }
        $bool = file_put_contents($file, $data);
        if (!$bool) {
            test("$table 备份失败" . mysqli_error() . $file);
        }
    }

    /**********文件夹删除函数*********************************/
    private static function deleteFile($url)
    {
        //先删除目录下的文件：
        if ($old = opendir($url)) {
            while (($file = readdir($old)) !== false) {
                if ($file != "." && $file != "..") {
                    $path = "{$url}/{$file}";
                    if (is_dir($path)) {
                        self::deleteFile($path);
                    } else {
                        unlink($path);
                    }
                }
            }
            closedir($old);
        }
        //删除当前文件夹：
        if (rmdir($url)) {
            return "deleteFile Yes";
        } else {
            return "deleteFile No";
        }
    }

    /**
     * 报工端登录
     *
     * @param array $data
     * @return array
     */
    public function reportLogin(array $data): array
    {
        if (empty($data['post']['company'])) {
            $json['warn'] = "请输入企业名称";
        } elseif (empty($data['post']['userName'])) {
            $json['warn'] = "请输入用户名";
        } elseif (preg_match(checkString, $data['post']['userName']) == 0) {
            $json['warn'] = "用户名格式有误";
        } elseif (empty($data['post']['password'])) {
            $json['warn'] = "请输入登录密码";
        } elseif (strlen($data['post']['password']) < 6 || strlen($data['post']['password']) > 20) {
            $json['warn'] = "登录密码不得低于六位或大于20位";
        } elseif (empty($data['post']['did'])) {
            $json['warn'] = "登录设备异常";
        } else {
            $password = $data['post']['password'];

            $company    = query("company", " name = '" . $data['post']['company'] . "' ", "coid,name");
            $user       = query("user", " userName = '" . $data['post']['userName'] . "' ");
            $adLoginNum = para("adLoginNum");//每日登录密码最大的错误次数
            if (empty($company['coid'])) {
                $json['warn'] = "企业【" . $data['post']['company'] . "】不存在";
            } elseif (empty($user['userName'])) {
                $json['warn'] = "用户名【" . $data['post']['userName'] . "】不存在";
            } elseif ($user['loginError'] >= $adLoginNum and $user['loginErrorDay'] == date("Y-m-d")) {
                $json['warn'] = "您今天登录密码输入错误次数已经超过" . $adLoginNum . "次，不能再登录了";
            } elseif ($user['state'] == "停用") {
                $json['warn'] = "您的账号处于停用状态，请联系行政人员！";
            } //登录密码输入错误
            elseif (verifyPwd($password, $user['password']) !== true) {
                if (isset($_SESSION['forgetPas']) && $data['post']['userName'] == $_SESSION['forgetPas']['name'] and verifyPwd($password, $_SESSION['forgetPas']['prove'])) {
                    //如果是点击忘记密码时发送到手机上的短信验证码
                    update([
                        "table" => "user",
                        "field" => [
                            "password"   => md5s($data['post']['password']),
                            "updateTime" => date("Y-m-d H:i:s"),
                        ],
                        "where" => " userName = '" . $data['post']['userName'] . "' ",
                    ]);
                    unset($_SESSION['forgetPas']['prove']);
                    $json['warn'] = 2;
                } else {
                    if ($user['loginError'] >= $adLoginNum) {
                        $user['loginError'] = 0;
                    }
                    $num    = $user['loginError'] + 1;
                    $remain = $adLoginNum - $num;//今天还能登录的次数
                    update([
                        "table" => "user",
                        "field" => [
                            "loginError"    => $num,
                            "loginErrorDay" => date("Y-m-d"),
                            "updateTime"    => date("Y-m-d H:i:s"),
                        ],
                        "where" => " userName = '" . $data['post']['userName'] . "' ",
                    ]);
                    $json['warn'] = "登录密码错误，您今天还可以登录" . $remain . "次";
                }
            } else {
                $json['warn'] = 2;
            }
            if ($json['warn'] == 2) {
                $this->rSet($user['uid'] . 'loginPage', 1);
                //登录密码错误次数清零
                update([
                    "table" => "user",
                    "field" => [
                        'deviceId'   => $data['post']['did'],
                        'loginError' => 0,
                    ],
                    "where" => " userName = '" . $data['post']['userName'] . "' ",
                ]);
                //添加登录记录
                insert([
                    "table" => "log",
                    "field" => [
                        "type" => "user",
                        "coid" => $company['coid'],
                        "stid" => $user['stid'],
                        "text" => $user['name'] . "登录了管理员后台，ip地址：" . getIp(),
                        "time" => date("Y-m-d H:i:s"),
                    ],
                ]);
                //创建登录session，返回跳转地址
                $_SESSION['stid']     = $user['stid'];
                $_SESSION['deviceId'] = $data['post']['did'];
                $_SESSION['coid']     = $company['coid'];
                $json['href']         = root . "pad/";
            }
        }
        return $json;
    }
}

//实例化对象
$libData = new libDataClass();
//打印结果
echo $libData->html(array("get" => $get, "post" => $post, "dataBase" => $conf));
